#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <stdint.h>
#include "msg_queue_interface.h"
#include "debug.h"
#include "misc.h"


#define PATHNAME        "."


typedef struct
{
    long mtype;
    char mtext[MSG_DATA_LEN];
} msgQueueBuf_t;


static int MsgQueue_Open(const char *pPathName, uint8_t projId, int msgFlag, int *pMsgId, key_t *pKey)
{
    key_t key;
    int msgId;

    if((key = ftok(pPathName, projId)) == -1)
    {
        perror("ftok");
        return -1;
    }
 
    if((msgId = msgget(key, msgFlag)) == -1)
    {
        // perror("msgget");
        return -2;
    }

    *pMsgId = msgId;
    *pKey = key;
    return 0;
}


int MsgQueue_Create(uint8_t projId)
{
    key_t key;
    int msgId, msgFlag, err;
    
    msgFlag = IPC_CREAT | 0666;
    if((err = MsgQueue_Open(PATHNAME, projId, msgFlag, &msgId, &key)) != 0)
    {
        PRINT_ERROR("Creat failure[%d]", err);
        return -1;
    }
   
    Misc_RecordIpc(projId, key, msgId);
    return 0;
}


int MsgQueue_Get(uint8_t projId, int *pMsgId)
{
    key_t key;
    int msgId, msgFlag, err;
    
    msgFlag = 0;
    if((err = MsgQueue_Open(PATHNAME, projId, msgFlag, &msgId, &key)) != 0)
    {
        // PRINT_ERROR("Get failure[%d]", err);
        return -1;
    }

    *pMsgId = msgId;
    return 0;
}


int MsgQueue_Delete(int msgId)
{
    if(msgctl(msgId, IPC_RMID, NULL) == -1)
    {
        perror("msgctl");
        return -1;
    }

    return 0;
}


int MsgQueue_Send(int msgId, const void *pBuff, long type, int flag)
{
    msgQueueBuf_t msgBuf = {0};

    msgBuf.mtype = type;
    memcpy(msgBuf.mtext, pBuff, MSG_DATA_LEN);

    if(msgsnd(msgId, &msgBuf, MSG_DATA_LEN, flag) == -1)
    {
        perror("msgsnd");
        return -1;
    }

    return 0;
}


int MsgQueue_Recv(int msgId, void *pBuff, long type, int flag)
{
    msgQueueBuf_t msgBuf = {0};

    if(msgrcv(msgId, &msgBuf, MSG_DATA_LEN, type, flag) == -1)
    {
        // perror("msgrcv");
        return -1;
    }

    memset(pBuff, '\0', MSG_DATA_LEN);
    memcpy(pBuff, msgBuf.mtext, MSG_DATA_LEN);
    return 0;    
}


/* 消息类型固定为1，由消息内容区分 */
int MsgQueue_Send1(int msgId, const void *pBuff)
{
    int err;

    if((err = MsgQueue_Send(msgId, pBuff, 1, 0)) != 0)
    {
        PRINT_WARN("Send failure[%d]", err);
        return -1;
    }

    return 0;
}


/* 消息类型固定为1，由消息内容区分 */
int MsgQueue_Recv1(int msgId, void *pBuff)
{
   int err;

    if((err = MsgQueue_Recv(msgId, pBuff, 1, 0)) != 0)
    {
        // PRINT_WARN("Recv failure[%d]", err);
        return -1;
    }

    return 0;   
}

